#ifndef __SELECT_SVR_H__
#define __SELECT_SVR_H__

#include <iostream>
#include <string>
#include <vector>
#include <sys/select.h>
#include <sys/time.h>
#include "Log.hpp"
#include "Sock.hpp"

#define BITS 8
#define NUM (sizeof(fd_set)*BITS)
#define FD_NONE -1

using namespace std;
class SelectServer
{
public:
    SelectServer(const uint16_t&port =8080):_port(port)
    {
        _listensock = Sock::Socket();
        Sock::Bind(_listensock,_port);
        Sock::Listen(_listensock);
        logMessage(DEBUG,"%s","create base socket success");
        for(int i =0;i<NUM;i++)
        {
            _fd_array[i] = FD_NONE;
        }
        _fd_array[0] = _listensock;
    }

    void Start()
    {
        while(true)
        {
            DebugPrint();

            fd_set rfds;
            FD_ZERO(&rfds);
            int maxfd = _listensock;
            for(int i =0;i<NUM;i++)
            {
                if(_fd_array[i] == FD_NONE) continue;
                FD_SET(_fd_array[i],&rfds);//将自己维护的数组加入到位图中；在河边设置一百个鱼竿
                if(maxfd<_fd_array[i]) maxfd = _fd_array[i];
            }

            int n = select(maxfd+1,&rfds,nullptr,nullptr,nullptr);
            switch (n)
            {
            case 0:
                logMessage(DEBUG,"%s","time out.....");
                break;
            case -1:
                logMessage(WARNING,"select error : %d:%s",errno,strerror(errno));
                break;
            default:
                logMessage(DEBUG,"get a new link event...");
                HandlerEvent(rfds);
                break;
            }
        }
    }

    ~SelectServer()
    {
        if(_listensock >=0)
        {
            close(_listensock);
        }
    }
private:
     void HandlerEvent(const fd_set&rfds)
     {
        for(int i =0;i<NUM;i++)
        {
            if(_fd_array[i]==FD_NONE) continue;
            //鱼竿此时表示有鱼，可以拿起鱼竿了
            if(FD_ISSET(_fd_array[i],&rfds))
            {
                //select 此时将位图中已经就绪的文件描述符拷贝到用户层；用户层根据套接字处理请求
                if(_fd_array[i]==_listensock) Accepter();
                else Recver(i);
            }
        }
     }

     void Accepter()
     {
        string clientip;
        uint16_t clientport =0;
        int sock = Sock::Accept(_listensock,&clientip,&clientport);
        if(sock<0)
        {
            logMessage(WARNING,"accept error");
            return ;
        }
        logMessage(DEBUG,"get a new line success : %s-%d:%d",clientip.c_str(),clientport,sock);
        int pos =1;
        for(;pos<NUM;pos++)
        {
            if(_fd_array[pos] == FD_NONE) break;
        }
        if(pos == NUM)
        {
            logMessage(WARNING,"%s:%d","select server already full ,close :%d",sock);
            close(sock);
        }
        else 
        {
            _fd_array[pos] = sock;
        }
     }

     void Recver(int pos)
     {
        logMessage(DEBUG,"MESSAGE IN , get io event :%d",_fd_array[pos]);
        char buffer[1024];
        int n = recv(_fd_array[pos],buffer,sizeof(buffer)-1,0);
        if(n>0)
        {
            buffer[n] =0;
            logMessage(DEBUG,"client[%d]:%s",_fd_array[pos],buffer);
        }
        else if(n==0)
        {
            logMessage(DEBUG,"client%d quit,me too//",_fd_array[pos]);
            close(_fd_array[pos]);
            _fd_array[pos] = FD_NONE;
        }
        else 
        {
            logMessage(WARNING,"%d sock recv error , %d : %s",_fd_array[pos],errno,strerror(errno));
            close(_fd_array[pos]);
            _fd_array[pos] = FD_NONE;
        }
     }

     void DebugPrint()
     {
        cout<<"_fd_array[]:";
        for(int i =0;i<NUM;i++)
        {
            if(_fd_array[i] == FD_NONE) continue;
            cout<<_fd_array[i]<<" ";
        }
        cout<<endl;
     }


private:
    uint16_t _port;
    int _listensock;
    int _fd_array[NUM];//select 维护的队列
};

#endif